<template>
  <div class="t-select-box" v-clickoutside="handleClose">
    <div
      class="t-input-wrap t-input-value"
      :class="[
        { unselect: selectedLabel === '' },
        { selected: selectedLabel !== '' },
        { disabled: disabled },
      ]"
      @click="changeSelectHandle"
    >
      <div class="t-input" ref="reference" :class="[{ isFocus: isFocused }]">
        {{ selectedLabel ? selectedLabel : "请选择" }}
      </div>
      <span class="icon-wrap">
        <i
          class="el-icon-arrow-down"
          style="font-size: 14px"
          :class="{ active: isFocused }"
        ></i>
        <i
          class="select-close el-icon-circle-close"
          @click.stop="clearSelectHandle"
          style="font-size: 14px"
        ></i>
      </span>
    </div>

    <div
      class="t-popup"
      ref="popup"
      :style="{ width: inputWidth + 'px', zIndex: zIndex }"
    >
      <transition name="el-zoom-in-top">
        <div class="t-popup-wrap" v-show="isFocused">
          <div class="t-popup-content" ref="content">
            <div class="t-input-wrap">
              <input
                type="text"
                class="t-input search-input"
                v-model="queryKey"
                :placeholder="searchPlaceholder"
                @keydown.enter.prevent="searchHandle"
              />
              <i class="el-icon-search" @click="searchHandle"></i>
              <i
                v-show="queryKey"
                class="el-icon-circle-close"
                @click.stop="searchCloseHandle"
                style="font-size: 14px"
              ></i>
            </div>
            <div
              class="scroll-wrap"
              :style="{
                height: checkScrollHeight,
                maxHeight: maxHeight + 'px',
              }"
              v-infinite-scroll="requestHandle"
              infinite-scroll-disabled="false"
              infinite-scroll-immediate="true"
              infinite-scroll-distance="1"
            >
              <div
                class="t-item"
                :class="{ checked: item.rlValue == value }"
                v-for="(item, index) in dataList"
                :key="index"
                @click="chooseHandle(item)"
              >
                {{ item.rlLabel }}
              </div>
              <div class="load-tips">
                {{ isLoadAll ? "到底了~" : "加载中..." }}
              </div>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
import Clickoutside from "element-ui/src/utils/clickoutside";
import { getDataList } from "@/api/base/base";
export default {
  directives: { Clickoutside },
  props: {
    searchPlaceholder: {
      type: String,
      default: "请输入关键字查询",
    },
    value: {
      require: true,
    },
    maxHeight: {
      type: Number,
      default: 244,
    },
    zIndex: {
      type: Number,
      default: 1024,
    },
    requestObj: {
      type: Object,
      default: () => {},
    },
    defaultParams: {
      type: Object,
      default: () => {},
    },
    disabled: {
      type: Boolean,
      default: true,
    },
    outSelectLabel: {
      type: String,
      default: "",
    },
    isSaveLoad: {
      type: Boolean,
      default: false,
    },
    ftObject: {
      type: Object,
      default: () => {},
    },
  },
  computed: {
    checkScrollHeight() {
      return `calc(100% - ${this.inputHeight + 6}px)`;
    },
  },
  data: () => ({
    inputWidth: 0,
    inputHeight: 0,
    selectedLabel: "",
    isFocused: false,
    dataList: [],
    queryKey: "",
    isRequestFlag: false,
    isLoadAll: false,
    searchParams: {
      current: 1,
      size: 20,
    },
  }),
  watch: {
    value(newVal) {
      if (newVal === "") this.selectedLabel = "";
    },

    isFocused(newVal) {
      if (newVal) {
        this.resetPopupHandle();
        this.searchParams[this.requestObj.searchKey] = "";
        if (Object.keys({ ...this.defaultParams }).length > 0) {
          for (let k in this.defaultParams) {
            this.searchParams[k] = this.defaultParams[k];
          }
        }
        this.$nextTick(() => {
          if (this.dataList.length > 0 && this.isSaveLoad) return;
          this.getDataList();
        });
      } else {
        this.resetParamsHandle();
      }
    },
    outSelectLabel(newVal) {
      if (this.value === "") return;
      this.selectedLabel = newVal;
    },
  },
  methods: {
    getDataList() {
      this.isRequestFlag = true;
      const { url, method, rlLabel, rlValue, resultKey, urlConfig } =
        this.requestObj;
      getDataList(url, method, this.searchParams, urlConfig)
        .then((res) => {
          if (res.data.code !== 200) return this.$message.error(res.msg);
          let dataKeyList = resultKey.split(",");
          let list = [];
          switch (dataKeyList.length) {
            case 1:
              list = res[dataKeyList[0]];
              break;
            case 2:
              list = res[dataKeyList[0]][dataKeyList[1]];
              break;
            case 3:
              list = res[dataKeyList[0]][dataKeyList[1]][dataKeyList[2]];
              break;
          }
          if (rlLabel) {
            const formatExp = /([a-zA-Z0-9_]+)/g;
            const matches = rlLabel.match(formatExp);
            list.forEach((item) => {
              item.rlValue = item[rlValue];
              if (matches) {
                item.rlLabel = rlLabel;
                matches.forEach((match) => {
                  if (item[match] !== undefined) {
                    item.rlLabel = item.rlLabel.replace(match, item[match]);
                  }
                });
              }
            });
          }
          this.dataList = [...this.dataList, ...list];
          this.isLoadAll = list.length < this.searchParams.size;
        })
        .finally(() => {
          this.isRequestFlag = false;
        });
    },
    searchHandle() {
      this.searchParams[this.requestObj.searchKey] = this.queryKey;
      this.searchParams.current = 1;
      this.dataList = [];
      this.getDataList();
    },
    handleClose() {
      this.isFocused = false;
    },
    changeSelectHandle() {
      if (this.disabled || this.isRequestFlag) return;
      this.isFocused = !this.isFocused;
    },
    requestHandle() {
      if (this.isRequestFlag || this.isLoadAll || !this.isFocused) return;
      this.searchParams.current++;
      this.getDataList();
    },
    chooseHandle(item) {
      if (item.rlValue === this.value) return (this.isFocused = false);
      item.isChangeFlag = this.value !== "";
      this.selectedLabel = item.rlLabel;
      this.$emit("update:outSelectLabel", item.rlLabel);
      this.$emit("input", item.rlValue);
      if (this.ftObject && this.ftObject.id) {
        item.ftId = this.ftObject.id;
      }
      this.$emit("change", item);
      this.$forceUpdate();
      this.isFocused = false;
    },
    resetPopupHandle() {
      this.$nextTick(() => {
        if (!this.$refs.popup) return;
        const el = this.$refs.popup;
        const range = this.$refs.reference.getBoundingClientRect();
        this.inputWidth = range.width;
        this.inputHeight = range.height;
        const windowHeight = window.innerHeight;
        el.style.left = range.left + "px";
        if (windowHeight - this.inputHeight - range.top - 6 > this.maxHeight) {
          el.style.top = range.top + this.inputHeight + 6 + "px";
        } else {
          el.style.top = range.top - el.offsetHeight - 6 + "px";
        }
      });
    },
    throttle(fn, delay = 100) {
      let timer = null;
      return function () {
        if (timer) return;
        timer = setTimeout(() => {
          fn.apply(this, arguments);
          timer = null;
        }, delay);
      };
    },
    resetParamsHandle() {
      if (this.value !== "" && this.isSaveLoad) return;
      this.queryKey = "";
      this.searchParams.current = 1;
      this.searchParams[this.requestObj.searchKey] = "";
      this.isRequestFlag = false;
      this.isLoadAll = false;
      this.dataList = [];
    },
    setLabel(label) {
      this.selectedLabel = label;
    },
    clearSelectHandle() {
      this.$emit("input", "");
      this.selectedLabel = "";
      this.$emit("update:outSelectLabel", "");
      if (this.ftObject) {
        this.$emit("clear", this.ftObject);
      }
    },
    searchCloseHandle() {
      this.queryKey = "";
      this.searchHandle();
    },
  },
  mounted() {
    this.selectedLabel = this.outSelectLabel;
    window.addEventListener("resize", this.throttle(this.resetPopupHandle));
  },
  beforeDestroy() {
    this.resetParamsHandle();
    window.removeEventListener("resize", this.throttle(this.resetPopupHandle));
  },
};
</script>

<style lang="scss" scoped>
.t-select-box {
  cursor: default;
  flex: 1;
  width: 100%;
  // min-width: 143px;
  .select-value {
    width: 100%;
    height: 32px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
  }
}
.t-input-wrap {
  position: relative;
  font-size: 0;
  .icon-wrap {
    position: absolute;
    height: 100%;
    right: 0;
    width: 30px;
  }
  .el-icon-arrow-down,
  .el-icon-search,
  .el-icon-circle-close {
    cursor: pointer;
    position: absolute;
    line-height: 16px;
    text-align: center;
    color: #999999;
    font-size: 16px;
    width: 16px;
    height: 16px;
    top: 0;
    right: 8px;
    bottom: 0;
    margin: auto;
    transition: all 0.3s;
    &.active {
      color: #0087d6;
      transform: rotate(180deg);
    }
  }
  .el-icon-search {
    left: 8px;
    right: auto;
  }
  .el-icon-circle-close {
    color: #c0c4cc;

    &:hover {
      color: #999999;
    }
    &.select-close {
      display: none;
    }
  }
  &.unselect {
    .t-input {
      color: #c0c4cc;
    }
  }
  &.selected {
    .icon-wrap:hover {
      .el-icon-arrow-down {
        display: none;
      }
      .el-icon-circle-close {
        display: block;
      }
    }
  }
  &.disabled {
    .t-input {
      cursor: no-drop;
      border-color: #e4e7ed;
      background-color: #eeeeee;
      color: #c0c4cc;
    }
    &:hover {
      .t-input {
        border-color: #e4e7ed !important;
      }
    }
  }
}
.t-input-value:hover {
  .t-input {
    border-color: $input-hover-color;
  }
}
.t-input {
  cursor: pointer;
  -webkit-appearance: none;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: rgba($color: #000000, $alpha: 0.9);
  display: inline-block;
  font-size: 14px;
  height: 32px;
  line-height: 30px;
  outline: none;
  padding: 0 30px 0 15px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.search-input {
  padding: 0 30px;
}
.t-input::placeholder {
  color: #c0c4cc;
}
.isFocus {
  border-color: #0087d6;
}

.t-popup {
  position: fixed;
  .t-popup-wrap {
    height: 100%;
    border-radius: 6px;
    overflow: hidden;
    background-color: #ffffff;
    box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.12),
      0px 4px 5px 0px rgba(0, 0, 0, 0.08), 0px 1px 10px 0px rgba(0, 0, 0, 0.05);
  }
  .t-popup-content {
    padding: 0 4px 8px 8px;
    width: auto;
    height: 100%;
    margin-top: 8px;
    margin-right: 4px;
    transition: all 0.3s;
    .scroll-wrap {
      margin-top: 4px;
      overflow-y: scroll;
      .load-tips {
        height: 28px;
        text-align: center;
        line-height: 28px;
        color: #c0c4cc;
        font-size: 14px;
      }
    }
    .t-item {
      min-height: 28px;
      padding: 0 8px;
      color: rgba($color: #000000, $alpha: 0.9);
      font-weight: 400;
      font-size: 14px;
      line-height: 28px;
      border-radius: 3px;
      cursor: pointer;
      transition: all 0.3s;
      margin: 0 4px 2px 0;
      &:hover {
        background-color: #f3f3f3;
      }
      &.checked {
        background-color: #e9e8fa;
        color: #0087d6;
      }
    }
  }
}
</style>
